Accessing XML Elements

Before we look at any code, let’s look at an example HTML document that uses and embedded XML Data Island to generate its content when the document is loaded in to the browser.  Remember, this technique is manipulating XML before it is displayed because it is generating the HTML to display to the user.  

First, let’s look at the XML Data Island, which is embedded in the HTML document.

<XML ID=employees>
<employees>
    <employee>
        <name>
            <first>John</first>
            <last>Doe</last>
        </name>
        <position>Programmer</position>
        <phone>
            <main>(714) 555-1000</main>
        </phone>
    </employee>
    <employee>
        <name>
            <first>Jane</first>
            <last>Doe</last>
        </name>
        <position>Systems Analyst</position>
        <phone>
            <main>(714) 555-2000</main>
        </phone>
    </employee>
</employees>
</XML>

File: Chapter 8\EmployeeDataIsland1.htm

A couple things to notice is the declaration of the XML Data Island using the <XML> and </XML> tags.  There is no XML processing instruction (i.e. <?xml version=”1.0”?>) since this is not an XML document.  Instead, it is an XML block contained within an HTML document.  Also notice the ID attribute in the opening <XML> tag.  The identifier specified in this attribute will be name by which the Data Island will be referred to as an object.  You can have multiple XML Data Islands within an HTML document, but they must each have a unique identifier.  In our example, our XML Data Island is referenced by the name “employees”.  XML Data Islands can appear just about anywhere within an HTML document.  It is a good practice to place them before the <BODY> tag so that they remain separate from the content definition of the document.

The next thing that we are going to look at is the JavaScript that uses the XML Data Island and generates the page

<H1>Employee Phone List</H1>
<HR>
<TABLE BORDER=1 WIDTH=100%>
	<TR>
		<TH>Last Name
		<TH>First Name
		<TH>Position
		<TH>Phone Number
	<TR>
<SCRIPT LANGUAGE="JavaScript">
<!--
	var xmlRoot;
	var xmlEmployee;
	var xmlName;
	var xmlPosition;
	var xmlPhone;
	var intCount;
	var intTotal;
	
	// Get the root element <employees>
	xmlRoot = employees.documentElement;
	
	// Get the total number of <employee> 
	// elements
	intTotal = xmlRoot.childNodes.length;
	
	// Iterate through all of the <employee>
	// elements and create an HTML table
	// containing their information.
	for (	intCount = 0;
			intCount < intTotal;
			intCount++ )
	{
		// Get the first employee element and 
		// assign the subsequent element objects.
		// We could have just used one JavaScript
		// variable to point to each XML object 
		// when we needed it, but this makes the 
		// code more readable for now.
		xmlEmployee = xmlRoot.childNodes.item(intCount);
		xmlName = xmlEmployee.childNodes.item( 0 );
		xmlPosition = xmlEmployee.childNodes.item(1);
		xmlPhone = xmlEmployee.childNodes.item(2);
		
		// Generate the next table row and
		// first cell.
		document.write("<TR><TD>" );
		
		// Write out the last and first names.
		document.write(xmlName.childNodes.item(1).text );
		document.write("<TD>" );
		document.write(xmlName.childNodes.item(0).text );
		document.write("<TD>" );
		
		// Write out the position.
		document.write(xmlPosition.text );
		document.write("<TD>" );
		
		// Write out the Phone number.
		document.write(xmlPhone.childNodes.item(0).text);
	}
-->
</SCRIPT>

</TABLE>

File: Chapter 8\EmployeeDataIsland1.htm

Let’s break down the script section by section.  First, notice that a <TABLE> tag is being used to specify the creation of an HTML table.  Our JavaScript is going to generate the contents of the table based on the data contained within the XML Data Island.

Before we do anything, we have to point a JavaScript object pointer to the XML Data Island’s root (or document) element.  This is done by using the .documentElement property.  It is through this object that we can get to the data within the Data Island. 
 
	// Get the root element <employees>
	xmlRoot = employees.documentElement;
	
Once we have a pointer to the root element, we need to find out how many child elements are in nested within it.  This will tell us how many employees (i.e. <employee> tags) are specified within the Data Island.

	// Get the total number of <employee> 
	// elements
	intTotal = xmlRoot.childNodes.length;

This code is a little tricky to understand.  From the root element object (xmlRoot), we reference a property named childNodes.  This is a collection of elements that are children of the current element, which in this case is the root.  This collection contains an object for each of these child elements, as you will see in a moment.  The collection is also an object, which has properties and methods.  One of these properties is named length.  The length property tells us the length of the collection, or in simpler terms, the number of elements contained within the collection.  This number reflects the number of <employee> elements contained within the root.  Based on our XML Data Island, the intTotal variable will be set to 2 since there are 2 <employee> elements contained in it.

Next, we will iterate through each of the employee elements, extract the information they contain, and generate the HTML document on the fly.

for (	intCount = 0;
		intCount < intTotal;
		intCount++ )
{
	. . .
}

Here we are using a for loop construct to iterate through the root object’s collection of elements.  This is a standard structure for Java, JavaScript, and C/C++.  The for statement has three parts:

	The Init-Expression
		This is where one or more values are initialized.  In this 
		case, we are initializing a counter to 0.  We will use this 
		counter to reference the elements within the collection by 
		ordinal position.  In JavaScript, arrays and collections are 
		0 based, which means the first element will be in ordinal 
		position 0.

	The Conditional-Expression
		If this comparison proves true, the code within the loop 
		block as identified with the open and close braces ({ }) will 
		execute.  If it proves false, the code will not execute and the 
		loop will end.  In this case, the comparison expression checks 
		to see if we have iterated through all of the elements in the 
		collection or not.  Notice that we do not perform an equality 
		comparison against the total number of elements in the 
		collection.  Since collections are 0 based, we want to loop 
		from 0 to intTotal - 1.  In this way, we will not exceed the 
	bounds of the collection.

	The Loop-Expression
		This expression will be executed before the conditional 
		expression is evaluated, and before the loop block code is 
		executed.  A point of note, if does not execute the first time 
		that the loop block is entered, but only on subsequent 
		executions.  In this case, we are using the ++ (pronounced 
		“plus-plus”) operator to increment our counter by one.  
		Each time the loop completes, our counter will be 
		incremented, then the conditional expression will be evaluated.

Next, we get a pointer to the current employee element by assigning a JavaScript object to the object within the collection using the childNodes collection’s item property.  Using the item property, we reference by ordinal position the <employee> element that we want from the collection.

	xmlEmployee = xmlRoot.childNodes.item(intCount);

We do this for each employee that is contained within the collection.  Once we have the <employee> element, we can reference each of the subsequent elements within it (i.e. <name>, <position> and <phone>).  Using the childNodes.item() method again, we can query the employee element object and get the data that we are looking for.  Each of these elements will be returned to us as an XML object.

	xmlName = xmlEmployee.childNodes.item( 0 );
	xmlPosition = xmlEmployee.childNodes.item(1);
	xmlPhone = xmlEmployee.childNodes.item(2);

Now that we have the elements as objects, we can reference there internal data and output it to the HTML document using the DOM’s document object and its write() method.

	// Generate the next table row and
	// first cell.
	document.write("<TR><TD>" );
		
	// Write out the last and first names.
	document.write(xmlName.childNodes.item(1).text );
	document.write("<TD>" );
	document.write(xmlName.childNodes.item(0).text );
	document.write("<TD>" );
		
	// Write out the position.
	document.write(xmlPosition.text );
	document.write("<TD>" );
		
	// Write out the Phone number.
	document.write(xmlPhone.childNodes.item(0).text

Notice that we not only write out the contents of the XML Data Island, but also HTML tags.  This is perfectly legal in JavaScript since we are simply writing to the document itself.  Once the browser has finished loading the HTML document and executing the script contained within it, it looks like this:

File: Chapter 8\EmployeeDataIsland1.htm in IE5.

If we view the source of the document inside of Notepad, we will not see much HTML, but instead, a lot of JavaScript.  This is because the HTML document was almost entirely generated on the client using the data within the XML Data Island.  However, once the document has been generated, the user is presented a static page to view.  

In our next lesson, we are going to discuss using Dynamic HTML (DHTML) to create a rich, dynamic user experience by updating the document based on the user’s interaction with the document.